/* Find smallest order which can satisfy the request. */
for ( i = order; i <= SHADOW_MAX_ORDER; i++ )
if ( !list_empty(&d->arch.paging.shadow.freelists[i]) )
- {
- sp = list_entry(d->arch.paging.shadow.freelists[i].next,
- struct shadow_page_info, list);
- list_del(&sp->list);
-
- /* We may have to halve the chunk a number of times. */
- while ( i != order )
- {
- i--;
- sp->order = i;
- list_add_tail(&sp->list, &d->arch.paging.shadow.freelists[i]);
- sp += 1 << i;
- }
- d->arch.paging.shadow.free_pages -= 1 << order;
-
- /* Init page info fields and clear the pages */
- for ( i = 0; i < 1<<order ; i++ )
- {
- /* Before we overwrite the old contents of this page,
- * we need to be sure that no TLB holds a pointer to it. */
- mask = d->domain_dirty_cpumask;
- tlbflush_filter(mask, sp[i].tlbflush_timestamp);
- if ( unlikely(!cpus_empty(mask)) )
- {
- perfc_incrc(shadow_alloc_tlbflush);
- flush_tlb_mask(mask);
- }
- /* Now safe to clear the page for reuse */
- p = sh_map_domain_page(shadow_page_to_mfn(sp+i));
- ASSERT(p != NULL);
- clear_page(p);
- sh_unmap_domain_page(p);
- INIT_LIST_HEAD(&sp[i].list);
- sp[i].type = shadow_type;
- sp[i].pinned = 0;
- sp[i].logdirty = 0;
- sp[i].count = 0;
- sp[i].backpointer = backpointer;
- sp[i].next_shadow = NULL;
- perfc_incr(shadow_alloc_count);
- }
- return shadow_page_to_mfn(sp);
- }
+ goto found;
/* If we get here, we failed to allocate. This should never happen.
* It means that we didn't call shadow_prealloc() correctly before
* we might free up higher-level pages that the caller is working on. */
SHADOW_PRINTK("Can't allocate %i shadow pages!\n", 1 << order);
BUG();
+
+ found:
+ sp = list_entry(d->arch.paging.shadow.freelists[i].next,
+ struct shadow_page_info, list);
+ list_del(&sp->list);
+
+ /* We may have to halve the chunk a number of times. */
+ while ( i != order )
+ {
+ i--;
+ sp->order = i;
+ list_add_tail(&sp->list, &d->arch.paging.shadow.freelists[i]);
+ sp += 1 << i;
+ }
+ d->arch.paging.shadow.free_pages -= 1 << order;
+
+ /* Init page info fields and clear the pages */
+ for ( i = 0; i < 1<<order ; i++ )
+ {
+ /* Before we overwrite the old contents of this page,
+ * we need to be sure that no TLB holds a pointer to it. */
+ mask = d->domain_dirty_cpumask;
+ tlbflush_filter(mask, sp[i].tlbflush_timestamp);
+ if ( unlikely(!cpus_empty(mask)) )
+ {
+ perfc_incrc(shadow_alloc_tlbflush);
+ flush_tlb_mask(mask);
+ }
+ /* Now safe to clear the page for reuse */
+ p = sh_map_domain_page(shadow_page_to_mfn(sp+i));
+ ASSERT(p != NULL);
+ clear_page(p);
+ sh_unmap_domain_page(p);
+ INIT_LIST_HEAD(&sp[i].list);
+ sp[i].type = shadow_type;
+ sp[i].pinned = 0;
+ sp[i].logdirty = 0;
+ sp[i].count = 0;
+ sp[i].backpointer = backpointer;
+ sp[i].next_shadow = NULL;
+ perfc_incr(shadow_alloc_count);
+ }
+ return shadow_page_to_mfn(sp);
}
int unmap_l2e = 0;
#if GUEST_PAGING_LEVELS == 2
+
/* Shadow l3 tables were built by sh_update_cr3 */
- if ( shadow_mode_external(d) )
- shadow_l3e = (shadow_l3e_t *)&v->arch.paging.shadow.l3table;
- else
- BUG(); /* PV 2-on-3 is not supported yet */
+ BUG_ON(!shadow_mode_external(d)); /* PV 2-on-3 is unsupported */
+ shadow_l3e = (shadow_l3e_t *)&v->arch.paging.shadow.l3table;
#else /* GUEST_PAGING_LEVELS == 3 */
if ( unlikely(!guest_mode(regs)) )
{
- char sig[5];
- /* Signature (ud2; .ascii "dbg") indicates dump state and continue. */
- if ( (__copy_from_user(sig, (char *)regs->eip, sizeof(sig)) == 0) &&
- (memcmp(sig, "\xf\xb""dbg", sizeof(sig)) == 0) )
+ struct bug_frame bug;
+ if ( (__copy_from_user(&bug, (char *)regs->eip, sizeof(bug)) == 0) &&
+ (memcmp(bug.ud2, "\xf\xb", sizeof(bug.ud2)) == 0) &&
+ (memcmp(bug.mov, BUG_MOV_STR, sizeof(bug.mov)) == 0) &&
+ (bug.ret == 0xc2) )
{
- show_execution_state(regs);
- regs->eip += sizeof(sig);
- return EXCRET_fault_fixed;
+ char *filename = (char *)bug.filename;
+ unsigned int line = bug.line & 0x7fff;
+ int is_bug = !(bug.line & 0x8000);
+ printk("Xen %s at %.50s:%d\n",
+ is_bug ? "BUG" : "State Dump", filename, line);
+ if ( !is_bug )
+ {
+ show_execution_state(regs);
+ regs->eip += sizeof(bug);
+ return EXCRET_fault_fixed;
+ }
}
DEBUGGER_trap_fatal(TRAP_invalid_op, regs);
show_execution_state(regs);
--- /dev/null
+#ifndef __IA64_BUG_H__
+#define __IA64_BUG_H__
+
+#define BUG() __bug(__FILE__, __LINE__)
+
+#endif /* __IA64_BUG_H__ */
--- /dev/null
+#ifndef __POWERPC_BUG_H__
+#define __POWERPC_BUG_H__
+
+#define BUG() __bug(__FILE__, __LINE__)
+
+#endif /* __POWERPC_BUG_H__ */
--- /dev/null
+#ifndef __X86_BUG_H__
+#define __X86_BUG_H__
+
+#ifdef __x86_64__
+#include <asm/x86_64/bug.h>
+#else
+#include <asm/x86_32/bug.h>
+#endif
+
+#define BUG() __BUG(__FILE__, __LINE__)
+#define dump_execution_state() __BUG(__FILE__, __LINE__ | 0x8000)
+
+#endif /* __X86_BUG_H__ */
#define compat_show_guest_stack(regs, lines) ((void)0)
#endif
-/* Dumps current register and stack state. */
-#define dump_execution_state() \
- /* NB. Needs interrupts enabled else we end up in fatal_trap(). */ \
- __asm__ __volatile__ ( "pushf ; sti ; ud2 ; .ascii \"dbg\" ; popf" )
-
extern void mtrr_ap_init(void);
extern void mtrr_bp_init(void);
--- /dev/null
+#ifndef __X86_32_BUG_H__
+#define __X86_32_BUG_H__
+
+struct bug_frame {
+ unsigned char ud2[2];
+ unsigned char mov[1];
+ unsigned long filename;
+ unsigned char ret;
+ unsigned short line;
+} __attribute__((packed));
+
+#define BUG_MOV_STR "\xbc"
+
+#define __BUG(file, line) \
+ asm volatile ( \
+ "ud2 ; .byte 0xbc ; .long %c1 ; ret $%c0" \
+ : : "i" (line), "i" (file) )
+
+#endif /* __X86_32_BUG_H__ */
--- /dev/null
+#ifndef __X86_64_BUG_H__
+#define __X86_64_BUG_H__
+
+struct bug_frame {
+ unsigned char ud2[2];
+ unsigned char mov[2];
+ unsigned long filename;
+ unsigned char ret;
+ unsigned short line;
+} __attribute__((packed));
+
+#define BUG_MOV_STR "\x48\xbc"
+
+#define __BUG(file, line) \
+ asm volatile ( \
+ "ud2 ; .byte 0x48,0xbc ; .quad %c1 ; ret $%c0" \
+ : : "i" (line), "i" (file) )
+
+#endif /* __X86_64_BUG_H__ */
#include <xen/types.h>
#include <xen/xmalloc.h>
#include <xen/string.h>
+#include <asm/bug.h>
+
+void __bug(char *file, int line) __attribute__((noreturn));
-extern void __bug(char *file, int line) __attribute__((noreturn));
-#define BUG() __bug(__FILE__, __LINE__)
#define BUG_ON(_p) do { if (_p) BUG(); } while ( 0 )
/* Force a compilation error if condition is true */